#include "stm32f10x.h"                  // Device header
#include "Uart.h"
#include "stdio.h"
#include "string.h"

CycleBuffer_t sUartBuffer;
static UartDMATransfer_t sUartDMATransferBuffer; 


bool Uart_Tx_DMA_Init()
{
    DMA_InitTypeDef stDMAInitDef;
    DMA_StructInit(&stDMAInitDef);

    //配置TX DMA
    stDMAInitDef.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);//注意要取地址
    stDMAInitDef.DMA_MemoryBaseAddr = (uint32_t)sUartDMATransferBuffer.aTXBuffer;
    stDMAInitDef.DMA_DIR = DMA_DIR_PeripheralDST;                   //外设站点作为目的地址
    stDMAInitDef.DMA_BufferSize = 0;
    stDMAInitDef.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    stDMAInitDef.DMA_MemoryInc = DMA_MemoryInc_Enable;
    stDMAInitDef.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    stDMAInitDef.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    stDMAInitDef.DMA_Mode = DMA_Mode_Normal;
    stDMAInitDef.DMA_Priority = DMA_Priority_Medium;
    stDMAInitDef.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel7, &stDMAInitDef);

    // 配置NVIC中断
    DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);       
    DMA_ClearFlag(DMA1_FLAG_TC7);
    NVIC_InitTypeDef stNVICInitDef;
    stNVICInitDef.NVIC_IRQChannel = DMA1_Channel7_IRQn;
    stNVICInitDef.NVIC_IRQChannelCmd = ENABLE;
    stNVICInitDef.NVIC_IRQChannelPreemptionPriority = 3;
    stNVICInitDef.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&stNVICInitDef);

	DMA_Cmd(DMA1_Channel7, DISABLE);
    return true;
}



bool Uart_Rx_DMA_Init()
{
     //配置RX DMA
	DMA_InitTypeDef stDMAInitDef;
	DMA_StructInit(&stDMAInitDef);
	DMA_StructInit(&stDMAInitDef);
	stDMAInitDef.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);//注意要取地址
	stDMAInitDef.DMA_MemoryBaseAddr = (uint32_t)sUartDMATransferBuffer.aRXBuffer;
	stDMAInitDef.DMA_DIR = DMA_DIR_PeripheralSRC;
	stDMAInitDef.DMA_BufferSize = sizeof(sUartDMATransferBuffer.aRXBuffer);
	stDMAInitDef.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	stDMAInitDef.DMA_MemoryInc = DMA_MemoryInc_Enable;
	stDMAInitDef.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte;
	stDMAInitDef.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	stDMAInitDef.DMA_Mode = DMA_Mode_Circular;
	stDMAInitDef.DMA_Priority = DMA_Priority_Medium;
	stDMAInitDef.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel6, &stDMAInitDef);

	DMA_Cmd(DMA1_Channel6, ENABLE);

	//配置NVIC中断
	DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
	DMA_ClearFlag(DMA1_FLAG_TC6);
	NVIC_InitTypeDef stNVICInitDef;
	stNVICInitDef.NVIC_IRQChannel = DMA1_Channel6_IRQn;
	stNVICInitDef.NVIC_IRQChannelCmd = ENABLE;
	stNVICInitDef.NVIC_IRQChannelPreemptionPriority = 3;
	stNVICInitDef.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&stNVICInitDef);

	return true;
}


bool Uart_DMA_Init()
{
    //开启DMA1外设时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    Uart_Tx_DMA_Init();
    Uart_Rx_DMA_Init();

    //使能串口DMA发送和接收请求
    USART_DMACmd(USART2, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);

    return true;
}

bool Uart_Init()
{
    uint8_t aBuffer[MAX_BUFF_SIZE] = {0};
    CycleBuffer_Init(&sUartBuffer, aBuffer, MAX_BUFF_SIZE);
    uart_init();                //初始化串口
    Uart_DMA_Init();            //初始化DMA
    return true;
}

void Uart_Send_With_DMA(uint8_t *pSendData, uint16_t nSendLen)
{
    if((NULL == pSendData) || (nSendLen > MAX_BUFF_SIZE))
    {
        return;
    }

    while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); //等待上次发送完成
   
    // 将待发送数据拷贝到DMA发送缓冲区
    memcpy(sUartDMATransferBuffer.aTXBuffer, pSendData, nSendLen);
    // 开启一次DMA发送
    DMA_Cmd(DMA1_Channel7, DISABLE);
    DMA_SetCurrDataCounter(DMA1_Channel7, nSendLen);
    DMA_Cmd(DMA1_Channel7, ENABLE);
}

void Uart_Send(uint8_t *pSendData, uint16_t nSendLen)
{
    Uart_Send_With_DMA(pSendData, nSendLen);
}

uint16_t Uart_Read(uint8_t *pReadBuff, uint16_t nReadCount)
{
    if ((NULL == pReadBuff))
    {
        return 0;
    }

    if (!CycleBuffer_IsEmpty(&sUartBuffer))//缓冲队列有数据
    {
        int16_t nCacheSize = CycleBuffer_GetCacheSize(&sUartBuffer);
        nReadCount = (nReadCount >= nCacheSize) ? nCacheSize : nReadCount;
        CycleBuffer_Read(&sUartBuffer, pReadBuff, nReadCount);    //读取数据
    }
    else
    {
        nReadCount = 0;        //没有数据
    }  
	return nReadCount;
}


void TransferDataFromDMABufferToCycleBuffer()
{
	uint16_t nReceiveCount = DMA_BUFFER_SIZE - DMA_GetCurrDataCounter(DMA1_Channel6);
	//将DMA数据搬到循环队列
	uint16_t nCacheRemain = CycleBuffer_GetRemainingSize(&sUartBuffer);
	if (nReceiveCount > nCacheRemain)
	{
		nReceiveCount = nCacheRemain;
	}
	
	CycleBuffer_Write(&sUartBuffer, sUartDMATransferBuffer.aRXBuffer, nReceiveCount);
	memset(sUartDMATransferBuffer.aRXBuffer, 0x00, sizeof(DMA_BUFFER_SIZE));
	
	int16_t nCount = CycleBuffer_GetCacheSize(&sUartBuffer);
	
	DMA_Cmd(DMA1_Channel6, DISABLE);
	DMA_SetCurrDataCounter(DMA1_Channel6, sizeof(sUartDMATransferBuffer.aRXBuffer));
	DMA_Cmd(DMA1_Channel6, ENABLE);
}


#ifdef __cplusplus
extern "C"
{
#endif


void DMA1_Channel6_IRQHandler(void)
{
	if (SET == DMA_GetITStatus(DMA1_IT_TC6))
    {
		DMA_ClearITPendingBit(DMA1_IT_TC6);   //清除中断标志位
        TransferDataFromDMABufferToCycleBuffer();
    }
}

void DMA1_Channel7_IRQHandler(void)
{
    if (SET == DMA_GetITStatus(DMA1_IT_TC7))
    {
        DMA_ClearITPendingBit(DMA1_IT_TC7);     //清除中断标志
        DMA_Cmd(DMA1_Channel7, DISABLE);        //关闭DMA
    }
}


void USART2_IRQHandler(void)
{
	if (SET == USART_GetITStatus(USART2, USART_IT_IDLE))
	{
		USART_ClearFlag(USART2, USART_IT_IDLE);
		TransferDataFromDMABufferToCycleBuffer();
	}
	USART_ClearITPendingBit(USART2, USART_IT_ORE);
}

#ifdef __cplusplus
}
#endif


